package com.lhy.tool.patchplugin.strategy;

import com.lhy.tool.patchplugin.model.CompileFileWrapper;
import com.lhy.tool.patchplugin.model.SrcFileWrapper;
import com.lhy.tool.patchplugin.model.TargetFileWrapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * war包中class文件的处理策略类 class文件可能有内部类存在
 */
@Slf4j
@Data
public class ClassStrategyImpl extends AbstractJavaFileStrategyImpl {

    private static final String CLASS = ".class";

    private static final String JAVA = ".java";

    private String srcPath ="/src/main/java/";
    private String target ="/target/classes/";


    public ClassStrategyImpl(String modulePath, List<String> targetWarModulePaths) {
        super(modulePath, targetWarModulePaths);
    }

    /**
     * 初始化模块路径名称
     */
    @PostConstruct
    protected void init() {
        int i = modulePath.substring(0, modulePath.length() - 1).lastIndexOf("/");
        this.moduleName = modulePath.substring(i + 1).replace("/", "");
    }

    @Override
    public boolean accept(SrcFileWrapper srcFileWrapper) {
        return srcFileWrapper.getAbsolutePath().startsWith(patchPluginProperties.getSrcPath() + modulePath)
                && srcFileWrapper.getAbsolutePath().endsWith(JAVA);
    }

    @Override
    public List<CompileFileWrapper> getCompileFiles(SrcFileWrapper srcFileWrapper) {

        String compileFilePath = srcFileWrapper.getAbsolutePath()
                .replace(srcPath, target).replace(JAVA, CLASS);
        File compileFile = new File(compileFilePath);
        List<CompileFileWrapper> compileFileWrappers = getCompileFile(compileFile);
        //处理内部类 规则是名称相同单包含$xxx尾缀
        List<CompileFileWrapper> innerClassCompileFiles = getInnerClassCompileFiles(compileFile);
        compileFileWrappers.addAll(innerClassCompileFiles);
        return compileFileWrappers;
    }

    /**
     * 获取编译后class文件加入到List中
     *
     * @param compileFile
     * @return
     */
    private List<CompileFileWrapper> getCompileFile(File compileFile) {
        CompileFileWrapper fileWrapper = new CompileFileWrapper(compileFile);
        List<CompileFileWrapper> compileFileWrappers = new ArrayList<>();
        compileFileWrappers.add(fileWrapper);
        return compileFileWrappers;
    }

    /**
     * 处理内部类 规则是名称相同单包含$xxx尾缀
     *
     * @param compileFile
     */
    private List<CompileFileWrapper> getInnerClassCompileFiles(File compileFile) {
        File[] innerClasses = compileFile.getParentFile()
                .listFiles((dir, name) -> Pattern.matches(name.split("\\$")[0] + "\\$.+\\.class", name));
        if (innerClasses != null) {
            return Arrays.stream(innerClasses)
                    .map(CompileFileWrapper::new)
                    .collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public List<TargetFileWrapper> getTargetFiles(CompileFileWrapper compileFileWrapper) {
        return targetWarModulePaths.stream()
                .map(targetWarModuleName -> compileFileWrapper.getAbsolutePath()
                        .replace(patchPluginProperties.getSrcPath() + modulePath + "target",
                                patchPluginProperties.getTargetPath() + targetWarModuleName + "WEB-INF"))
                .map(File::new)
                .map(TargetFileWrapper::new)
                .collect(Collectors.toList());
    }


}
